package state;

import stateframework_particle.view.StateFramework_ParticleResources;

public class Pointer extends Sprite implements KeySpriteListener, TimerListener {
  private static GameImage DEFAULT_ICON = null;
  private int activeKeyCode = Key.FIRE;
  private int step = 0;
  private int dx = 0;
  private int dy = 0;
  private boolean allowUseNumberKey = false;
  private Sprite lastMoveOnItem = null;
  private Sprite currentMoveOnItem = null;

  private int boundX = 0;
  private int boundY = 0;
  private int boundWidth = GameConstants.SCREEN_WIDTH;
  private int boundHeight = GameConstants.SCREEN_HEIGHT;

  /**
   * Khởi tạo pointer
   * 
   * @param manager - Manager quản lý
   * @param systemCanvas - SystemCanvas của hệ thống
   */
  public Pointer(Manager manager) {
    super(createDefaultIcon(), manager, GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT / 2, GameConstants.TOP_LEFT_ANCHOR);
    setKeyListener(this);
  }

  private static GameImage createDefaultIcon() {
    if (DEFAULT_ICON == null) {
      DEFAULT_ICON = new GameImage(StateFramework_ParticleResources.image_p_arrow, null, null).setStatic(true);
    }
    return DEFAULT_ICON;
  }

  public void resetToDefaultImage() {
    setImage(createDefaultIcon());
  }

  public boolean isUseDefaultImage() {
    return getImage() == createDefaultIcon();
  }

  /**
   * Lấy active code hiện tại đang xử dụng
   * 
   * @return active code
   */
  public int getActiveKeyCode() {
    return activeKeyCode;
  }

  /**
   * Thay đổi phím active của pointer (giống như Mouse Left của windows)
   * 
   * @param activeKeyCode1 - active code cập nhật
   */
  public void setActiveKeyCode(int activeKeyCode1) {
    this.activeKeyCode = activeKeyCode1;
  }

  public final void useMouseMoveEvent() {
    setTimerListener(this);
  }

  public void setActivePosition(int dx1, int dy1) {
    this.dx = dx1;
    this.dy = dy1;
  }

  public int getPointerX() {
    return _x + dx;
  }

  public int getPointerY() {
    return _y + dy;
  }

  public boolean isAllowUseNumberKey() {
    return allowUseNumberKey;
  }

  public void setAllowUseNumberKey(boolean isAllowUseNumberKey) {
    this.allowUseNumberKey = isAllowUseNumberKey;
  }

  public void keyPressed(Sprite source, int keyCode) {
    if (keyCode == activeKeyCode) {
      _manager.getParent().doMousePressed(_x + dx, _y + dy);
    }
  }

  public void keyReleased(Sprite source, int keyCode) {
    if (keyCode == activeKeyCode) {
      _manager.getParent().doMouseReleased(_x + dx, _y + dy);
    }
  }

  public void keyRepeated(Sprite source, int keyCode) {
    step = (int) ((System.currentTimeMillis() - GameGlobal.systemCanvas.getKeyRepeatHandle().getKeyRepeatStartTime()) >> 4L);
    int x1 = this._x + dx;
    int y1 = this._y + dy;

    switch (keyCode) {
    case Key.LEFT:
      if (x1 > boundX + step) {
        x1 -= step;
      } else {
        x1 = boundX;
      }
      break;
    case Key.RIGHT:
      if (boundX + boundWidth > x1 + step) {
        x1 += step;
      } else {
        x1 = boundX + boundWidth;
      }
      break;
    case Key.UP:
      if (y1 > boundY + step) {
        y1 -= step;
      } else {
        y1 = boundY;
      }
      break;
    case Key.DOWN:
      if (boundY + boundHeight > y1 + step) {
        y1 += step;
      } else {
        y1 = boundY + boundHeight;
      }
      break;
    }

    if (allowUseNumberKey) {
      switch (keyCode) {
      case Key.K_4: // Left
        if (x1 > boundX + step) {
          x1 -= step;
        } else {
          x1 = boundX;
        }
        break;
      case Key.K_6: // Right
        if (boundX + boundWidth > x1 + step) {
          x1 += step;
        } else {
          x1 = boundX + boundWidth;
        }
        break;
      case Key.K_2: // Up
        if (y1 > boundY + step) {
          y1 -= step;
        } else {
          y1 = boundY;
        }
        break;
      case Key.K_8: // Down
        if (boundY + boundHeight > y1 + step) {
          y1 += step;
        } else {
          y1 = boundY + boundHeight;
        }
        break;
      }
    }
    setPosition(x1 - dx, y1 - dy);
  }

  public void doTask() {
    if (_manager != null) {
      currentMoveOnItem = null;
      _manager.getParent().doMouseMoved(_x + dx, _y + dy);

      if ((lastMoveOnItem != null) && (lastMoveOnItem != currentMoveOnItem)) {
        lastMoveOnItem._mouseMoveListener.mouseMoveOut(lastMoveOnItem, _x + dx, _y + dy);
      }
      lastMoveOnItem = currentMoveOnItem;
      currentMoveOnItem = null;
    }
  }

  public void setCurrentMoveOnItem(Sprite currentMoveOnItem1) {
    this.currentMoveOnItem = currentMoveOnItem1;
  }

  public Sprite getCurrentMoveOnItem() {
    return lastMoveOnItem;
  }

  public void setBound(int x, int y, int width, int height) {
    boundX = x;
    boundY = y;
    boundWidth = width;
    boundHeight = height;
  }

  public Sprite detroy() {
    super.detroy();
    lastMoveOnItem = null;
    currentMoveOnItem = null;
    return this;
  }
}
